#include "stdafx.h"
#include "Buffer.h"

////////////////////////////////////////////////////////////////////////////////
// string trimmer
////////////////////////////////////////////////////////////////////////////////
BOOL IsSpace(TCHAR ch)
{
	switch (ch)
	{
	case (_T(' ')):
	case (_T('\t')):
	case (_T('\r')):
	case (_T('\n')):
		return TRUE;
	}
	return FALSE;
}

////////////////////////////////////////////////////////////////////////////////
// CBuffer implementation
CBuffer::CBuffer()
{
    m_pBufStart = m_abFixedBuf;
    m_pBufMax	= &m_abFixedBuf[128];
    m_pBufRdCur = m_pBufWrCur = m_pBufStart;
}

CBuffer::~CBuffer()
{
    if (m_pBufStart != m_abFixedBuf) 
		delete [] m_pBufStart;
}

void CBuffer::Reserve(const size_t nBytes)
{
    if (nBytes <= Capacity()) 
		return;

    LTrim();

    if (nBytes <= Capacity()) 
		return;

    size_t nNewBufSize = m_pBufMax - m_pBufStart;
    do 
    { 
        nNewBufSize += nNewBufSize / 2; 
    }
    while (nNewBufSize < m_pBufWrCur - m_pBufStart + nBytes);

    BYTE* pNewBufStart = new BYTE[nNewBufSize];
    if (pNewBufStart == NULL) 
		throw;

    ::memcpy(pNewBufStart, Data(), Size());
    
	if (m_pBufStart != m_abFixedBuf) 
		delete [] m_pBufStart;

    size_t nSize = Size();
    m_pBufStart = pNewBufStart;
    m_pBufMax = m_pBufStart + nNewBufSize;
    m_pBufRdCur = m_pBufStart;
    m_pBufWrCur = m_pBufStart + nSize;
}

void CBuffer::Clear()
{
    m_pBufWrCur = m_pBufRdCur = m_pBufStart;
}

void CBuffer::ReadBytes(void* pBuf, const size_t nBytes)
{
    if (nBytes > Size()) 
		throw

    ::memcpy(pBuf, Data(), nBytes);
    m_pBufRdCur += nBytes;
}

void CBuffer::WriteBytes(const void* pBuf, const size_t nBytes)
{
    Reserve(nBytes);
    ::memcpy(m_pBufWrCur, pBuf, nBytes);
    m_pBufWrCur += nBytes;
}

void CBuffer::LTrim()
{
    if (m_pBufStart != m_pBufRdCur)
    {
        ::memmove(m_pBufStart, m_pBufRdCur, m_pBufWrCur - m_pBufRdCur);
        m_pBufWrCur -= m_pBufRdCur - m_pBufStart;
        m_pBufRdCur = m_pBufStart;
    }
}

void CBuffer::RTrim()
{
    if (m_pBufStart == m_abFixedBuf || m_pBufWrCur == m_pBufMax) 
		return;

    size_t nNewBufSize = m_pBufWrCur - m_pBufStart;
    size_t nRdCur = GetRdCur();
    size_t nWrCur = GetWrCur();
    BYTE* pNewBufStart = NULL;
    
    if (nNewBufSize <= FIXED_BUFFER_SIZE)
    {
        pNewBufStart = m_abFixedBuf;
        nNewBufSize = FIXED_BUFFER_SIZE;
    }
    else 
        pNewBufStart = new BYTE[nNewBufSize];
    
    if (pNewBufStart == NULL) 
		return;

    ::memcpy(pNewBufStart, m_pBufStart, nNewBufSize);
    if (m_pBufStart != m_abFixedBuf) 
		delete [] m_pBufStart;

    m_pBufStart = pNewBufStart;
    m_pBufMax	= pNewBufStart + nNewBufSize;
    m_pBufRdCur = pNewBufStart + nRdCur;
    m_pBufWrCur = pNewBufStart + nWrCur;
}

void CBuffer::Trim()
{
    LTrim();
    RTrim();
}

